package api

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
	"hcy-api/lib/http"
	"hcy-api/lib/id"
	"hcy-api/lib/utils"
	"hcy-api/structs/idp"
	"hcy-api/structs/tables"
	"idp/global"
	"idp/repository"
	"time"
)

var BranchApi = new(branchApi)

type branchApi struct {
}

func (api branchApi) GetOfficePoint(c *gin.Context) {
	in := struct {
		Id int64 `uri:"id"`
	}{}
	if err := c.ShouldBindUri(&in); err != nil {
		http.BadWithParamsError(c)
		return
	}
	m, err := repository.BranchRepository.GetBranchOfficePointByBranchId(in.Id)
	if err != nil {
		http.BadWithDB(c, err)
		return
	}
	http.Ok(c, m)
}

func (api branchApi) SaveOfficePoint(c *gin.Context) {
	var in tables.IdpOfficePoint
	if err := c.ShouldBindJSON(&in); err != nil {
		http.BadWithParamsError(c)
		return
	}
	self := http.GetCurrentUser(c)
	in.Id = id.GetSnowId()
	in.AutoCreateInfo = tables.AutoCreateInfo{
		Creator:   self.Nickname,
		CreatorId: self.UserID,
		CreatedAt: time.Now().Unix(),
	}
	old, err := repository.BranchRepository.GetBranchOfficePointByBranchId(in.BranchId)
	if err != nil {
		http.BadWithDB(c, err)
		return
	}
	if old.Id == 0 {
		err = repository.BranchRepository.SaveBranchOfficePoint(&in)
		if err != nil {
			http.BadWithDB(c, err)
			return
		}
	} else {
		old.JsonStr = in.JsonStr
		old.BackGroundImg = in.BackGroundImg
		if err = repository.BranchRepository.UpdateBranchOfficePoint(&old); err != nil {
			http.BadWithDB(c, err)
			return
		}
	}
	http.OK204(c)
}

func (api branchApi) GetCityCode(c *gin.Context) {
	self := http.GetCurrentUser(c)
	code, err := repository.BranchRepository.GetCityCode(self.UserID)
	if err != nil {
		http.BadWithDB(c, err)
		return
	}
	http.Ok(c, code)
}

func (api branchApi) Create(c *gin.Context) {
	var in idp.AddBranchDto
	if err := c.ShouldBindJSON(&in); err != nil {
		http.BadWithParamsError(c)
		return
	}
	self := http.GetCurrentUser(c)
	err := global.DB.Transaction(func(tx *gorm.DB) error {
		branch := &tables.IdpBranch{
			Id:       id.GetSnowId(),
			Name:     in.Name,
			CityCode: in.CityCode,
			Lng:      in.Lng,
			Lat:      in.Lat,
			PlanePic: in.PlanePic,
			TitlePic: in.TitlePic,
			Admin:    in.Admin,
			Tel:      in.Tel,
			AutoCreateInfo: tables.AutoCreateInfo{
				Creator:   self.Nickname,
				CreatorId: self.UserID,
				CreatedAt: time.Now().Unix(),
				UpdatedAt: 0,
				DeletedAt: 0,
			},
		}
		if err := tx.Create(branch).Error; err != nil {
			return err
		}
		m := &tables.IdpMapBranchUser{
			Uid:      self.UserID,
			BranchId: branch.Id,
		}
		if err := tx.Create(m).Error; err != nil {
			return err
		}
		return nil
	})
	if err != nil {
		http.BadWithDB(c, err)
		return
	}
	http.OK204(c)
}

func (api branchApi) Update(c *gin.Context) {
	var in idp.UpdateBranchDto
	if err := c.ShouldBindJSON(&in); err != nil {
		http.BadWithParamsError(c)
		return
	}
	var old tables.IdpBranch
	if err := global.DB.Model(&tables.IdpBranch{}).Where(&tables.IdpBranch{Id: in.Id}).Find(&old).Error; err != nil {
		http.BadWithDB(c, err)
		return
	}
	old.Name = in.Name
	old.CityCode = in.CityCode
	old.Lng = in.Lng
	old.Lat = in.Lat
	old.PlanePic = in.PlanePic
	old.TitlePic = in.TitlePic
	old.Admin = in.Admin
	old.Tel = in.Tel
	if err := global.DB.Updates(&old).Error; err != nil {
		http.BadWithDB(c, err)
		return
	}
	http.OK204(c)
}

func (api branchApi) Delete(c *gin.Context) {
	in := struct {
		Id int64 `uri:"id,string"`
	}{}
	if err := c.ShouldBindUri(&in); err != nil {
		http.BadWithParamsError(c)
		return
	}
	err := global.DB.Transaction(func(tx *gorm.DB) error {
		if err := tx.Where(&tables.IdpMapBranchUser{BranchId: in.Id}).Delete(&tables.IdpMapBranchClient{}).Error; err != nil {
			return err
		}
		if err := tx.Where(&tables.IdpMapBranchClient{BranchId: in.Id}).Delete(&tables.IdpMapBranchClient{}).Error; err != nil {
			return err
		}
		if err := tx.Where(&tables.IdpBranch{Id: in.Id}).Delete(&tables.IdpBranch{}).Error; err != nil {
			return err
		}
		return nil
	})
	if err != nil {
		http.BadWithDB(c, err)
		return
	}
	http.OK204(c)
}

func (api branchApi) Page(c *gin.Context) {
	var in idp.SearchBranchPage
	if err := c.ShouldBindQuery(&in); err != nil {
		http.BadWithParamsError(c)
		return
	}
	self := http.GetCurrentUser(c)
	tx := global.DB.Model(&tables.IdpBranch{})
	if self.AccountLv != tables.AccountLvForRoot {
		tx.Where("id in (select branch_id from idp_map_branch_user where uid =?) ")
	}
	if in.Name != "" {
		tx.Where("name like ?", fmt.Sprintf("%%%s%%", in.Name))
	}
	var total int64
	var li []tables.IdpBranch
	err := tx.Count(&total).Offset((in.PageNum - 1) * in.PageSize).Limit(in.PageSize).Find(&li).Error
	if err != nil {
		http.BadWithDB(c, err)
		return
	}
	http.OkPage(c, li, total)
}

func (api branchApi) List(c *gin.Context) {
	self := http.GetCurrentUser(c)
	tx := global.DB.Model(&tables.IdpBranch{})
	if self.AccountLv != tables.AccountLvForRoot {
		tx.Where("id in (select branch_id from idp_map_branch_user where uid =?) ")
	}
	var li []tables.IdpBranch
	err := tx.Find(&li).Error
	if err != nil {
		http.BadWithDB(c, err)
		return
	}
	http.Ok(c, li)
}

func (api branchApi) BindUser(c *gin.Context) {
	var in idp.BranchBindUserDto
	if err := c.ShouldBindJSON(&in); err != nil {
		http.BadWithParamsError(c)
		return
	}
	err := global.DB.Transaction(func(tx *gorm.DB) error {
		err := tx.Where(&tables.IdpMapBranchUser{BranchId: in.BranchId}).Delete(&tables.IdpMapBranchUser{}).Error
		if err != nil {
			return err
		}
		in.UserIds = append(in.UserIds, tables.RootId)
		li := make([]tables.IdpMapBranchUser, 0)
		for _, v := range in.UserIds {
			li = append(li, tables.IdpMapBranchUser{
				Uid:      v,
				BranchId: in.BranchId,
			})
		}
		return tx.Model(&tables.IdpMapBranchUser{}).CreateInBatches(&li, len(li)).Error
	})
	if err != nil {
		http.BadWithDB(c, err)
		return
	}
	http.OK204(c)
}

func (api branchApi) BoundUserId(c *gin.Context) {
	in := struct {
		Id int64 `uri:"id,string"`
	}{}
	if err := c.ShouldBindUri(&in); err != nil {
		http.BadWithParamsError(c)
		return
	}
	ids, err := repository.BranchRepository.FindMapUidByBranchId(in.Id)
	if err != nil {
		http.BadWithDB(c, err)
		return
	}
	http.Ok(c, utils.StringArrayInt64(ids))
}
